package com.riversql.dbtree;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;

import com.riversql.sql.SQLConnection;
import com.riversql.sql.SQLDatabaseMetaData;
import com.riversql.sql.SQLDatabaseMetaData.IDBMSProductNames;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class DatabaseNode extends DBNode implements IStructureNode {

	@Override
	public void refresh() {
		init();
		super.refresh();
	}

	private boolean supportsCatalogs;
	private boolean supportsSchemas;

	private String sessionName;
	private String[] catalogs;

	public DatabaseNode(SQLConnection conn, String sessionName) {
		super(conn);
		this.sessionName = sessionName;
		init();
	}

	private void init() {
		SQLDatabaseMetaData metadata = conn.getSQLMetaData();

		try {
			supportsCatalogs = metadata.supportsCatalogs();
		} catch (SQLException ex) {
		}

		supportsSchemas = false;
		try {
			supportsSchemas = metadata.supportsSchemas();
		} catch (SQLException e) {
		}
		if (supportsCatalogs) {
			catalogs = null;
			try {
				catalogs = metadata.getCatalogs();
				if (catalogs == null || catalogs.length == 0)
					supportsCatalogs = false;
			} catch (Exception e) {
				supportsCatalogs = false;
			}
		}
	}

	public String[] getCatalogs() {
		return catalogs;
	}

	public boolean supportsCatalogs() {
		return supportsCatalogs;
	}

	public boolean supportsSchemas() {
		return supportsSchemas;
	}

	@Override
	protected void nodeLoad() throws SQLException {
		children.clear();
		SQLDatabaseMetaData metadata = conn.getSQLMetaData();

		if (supportsCatalogs && supportsSchemas) {

			if (catalogs != null) {
				String[] schemas = metadata.getSchemas();
				String dbname = metadata.getDatabaseProductName();
				if (dbname.equals(IDBMSProductNames.MICROSOFT_SQL)) {
					ArrayList<String> tmpList = new ArrayList<String>();
					tmpList.addAll(Arrays.asList(schemas));
					if (tmpList.indexOf("sys") == -1)
						tmpList.add("sys");
					schemas = tmpList.toArray(new String[tmpList.size()]);
				}

				for (int i = 0; i < catalogs.length; ++i) {
					final String catalogName = catalogs[i];
					children.add(new CatalogOfSchemasNode(catalogName, schemas,
							conn));

				}
			} else {
				if (supportsSchemas) {
					final String[] schemas = metadata.getSchemas();
					for (int i = 0; i < schemas.length; ++i) {
						final String schemaName = schemas[i];
						children.add(new SchemaNode(schemaName, conn));
					}
				}
			}

		} else if (supportsCatalogs && !supportsSchemas) {
			for (int i = 0; i < catalogs.length; ++i) {
				final String catalogName = catalogs[i];
				children.add(new CatalogNode(catalogName, conn));
			}
		} else if (supportsSchemas) {
			final String[] schemas = metadata.getSchemas();
			for (int i = 0; i < schemas.length; ++i) {
				final String schemaName = schemas[i];
				children.add(new SchemaNode(schemaName, conn));
			}
		} else {
			children.add(new CatalogNode("-", conn, true));
		}

	}

	public String getName() {
		return sessionName;
	}

	public JSONObject toJSON() throws JSONException {
		JSONObject obj = new JSONObject();
		obj.put("text", getName());
		obj.put("id", getId());
		obj.put("leaf", isLeaf());
		obj.put("type", getType());
		obj.put("cls", getCls());

		JSONArray arr = new JSONArray();
		arr.put(obj);
		JSONObject ret = new JSONObject();
		ret.put("nodes", arr);

		return ret;
	}

	public String getType() {
		return "dtbs";
	}

	public String getCls() {
		return "database";

	}

	public boolean isLeaf() {
		return false;
	}
}
